{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.5909, 0.5652, 0.3517],\n",
      "        [0.1279, 0.5704, 0.0485],\n",
      "        [0.7846, 0.2919, 0.1320],\n",
      "        [0.6687, 0.0028, 0.7029],\n",
      "        [0.9940, 0.1200, 0.0307]])\n",
      "tensor([[0.7144, 0.2542, 0.4102],\n",
      "        [0.9046, 0.5248, 0.0038],\n",
      "        [0.4042, 0.4281, 0.1828],\n",
      "        [0.2656, 0.8508, 0.4685],\n",
      "        [0.1566, 0.4256, 0.4397]])\n",
      "tensor([[0, 0, 0],\n",
      "        [0, 0, 0],\n",
      "        [0, 0, 0],\n",
      "        [0, 0, 0],\n",
      "        [0, 0, 0]])\n",
      "tensor([5.5000, 3.0000])\n"
     ]
    }
   ],
   "source": [
    "# 不初始化\n",
    "x = torch.empty(5, 3)\n",
    "print(x)\n",
    "# 随机初始化\n",
    "x = torch.rand(5, 3)\n",
    "print(x)\n",
    "# 零矩阵(Long型)\n",
    "x = torch.zeros(5, 3, dtype=torch.long)\n",
    "print(x)\n",
    "# 直接使用数据\n",
    "x = torch.tensor([5.5, 3])\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[1., 1., 1.],\n",
      "        [1., 1., 1.],\n",
      "        [1., 1., 1.],\n",
      "        [1., 1., 1.],\n",
      "        [1., 1., 1.]], dtype=torch.float64)\n",
      "tensor([[-2.1484,  0.2887, -0.1204],\n",
      "        [ 0.1010,  0.6711, -0.3246],\n",
      "        [-0.4562,  2.7470,  0.4858],\n",
      "        [-0.6075, -0.2066,  0.0455],\n",
      "        [ 1.1387, -0.1143,  0.8121]])\n",
      "torch.Size([5, 3])\n"
     ]
    }
   ],
   "source": [
    "# 基于已有 tensor 创建\n",
    "x = x.new_ones(5, 3, dtype=torch.double)\n",
    "print(x)\n",
    "# 相同维度的正态分布 改变 dtype\n",
    "x = torch.randn_like(x, dtype=torch.float)\n",
    "print(x)\n",
    "# 获取维度\n",
    "print(x.size())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[-2.1282,  1.0202,  0.0597],\n",
      "        [ 0.4977,  1.6146,  0.5598],\n",
      "        [ 0.1867,  3.5107,  1.2422],\n",
      "        [-0.0934, -0.1602,  0.4123],\n",
      "        [ 1.7722,  0.0324,  1.7686]])\n",
      "tensor([[-2.1282,  1.0202,  0.0597],\n",
      "        [ 0.4977,  1.6146,  0.5598],\n",
      "        [ 0.1867,  3.5107,  1.2422],\n",
      "        [-0.0934, -0.1602,  0.4123],\n",
      "        [ 1.7722,  0.0324,  1.7686]])\n",
      "tensor([[-2.1282,  1.0202,  0.0597],\n",
      "        [ 0.4977,  1.6146,  0.5598],\n",
      "        [ 0.1867,  3.5107,  1.2422],\n",
      "        [-0.0934, -0.1602,  0.4123],\n",
      "        [ 1.7722,  0.0324,  1.7686]])\n",
      "tensor([[-2.1282,  1.0202,  0.0597],\n",
      "        [ 0.4977,  1.6146,  0.5598],\n",
      "        [ 0.1867,  3.5107,  1.2422],\n",
      "        [-0.0934, -0.1602,  0.4123],\n",
      "        [ 1.7722,  0.0324,  1.7686]])\n"
     ]
    }
   ],
   "source": [
    "# 加法操作\n",
    "y = torch.rand(5, 3)\n",
    "# way 1\n",
    "print(x + y)\n",
    "# way 2\n",
    "print(torch.add(x, y))\n",
    "# way 3\n",
    "result = torch.empty(5, 3)\n",
    "torch.add(x, y, out=result)\n",
    "print(result)\n",
    "# way 4\n",
    "y.add_(x)  # pytorch 中任何会改变原有变量的都有_\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.2713,  0.2141, -1.0443, -0.1400],\n",
      "        [-0.3378, -1.3428, -2.8072, -0.3751],\n",
      "        [ 0.3984, -0.6795,  1.9339, -0.0822],\n",
      "        [-0.2130,  0.4647,  0.7391,  0.3135]])\n",
      "tensor([ 1.2713,  0.2141, -1.0443, -0.1400, -0.3378, -1.3428, -2.8072, -0.3751,\n",
      "         0.3984, -0.6795,  1.9339, -0.0822, -0.2130,  0.4647,  0.7391,  0.3135])\n",
      "tensor([[ 1.2713,  0.2141, -1.0443, -0.1400, -0.3378, -1.3428, -2.8072, -0.3751],\n",
      "        [ 0.3984, -0.6795,  1.9339, -0.0822, -0.2130,  0.4647,  0.7391,  0.3135]])\n"
     ]
    }
   ],
   "source": [
    "# 改变 tensor 大小或形状\n",
    "x = torch.randn(4, 4)\n",
    "y = x.view(16)\n",
    "z = x.view(-1, 8)  # -1 代表 None\n",
    "print(x)\n",
    "print(y)\n",
    "print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([0.3622])\n",
      "0.362198144197464\n"
     ]
    }
   ],
   "source": [
    "# 获取 tensor 的值(仅当只有一个元素时)\n",
    "x = torch.randn(1)\n",
    "print(x)\n",
    "print(x.item())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1., 1., 1., 1., 1.])\n",
      "[1. 1. 1. 1. 1.]\n"
     ]
    }
   ],
   "source": [
    "# 结合 numpy\n",
    "a = torch.ones(5)\n",
    "print(a)\n",
    "b = a.numpy()\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([2., 2., 2., 2., 2.])\n",
      "[2. 2. 2. 2. 2.]\n"
     ]
    }
   ],
   "source": [
    "# 同时改变\n",
    "a.add_(1)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2. 2. 2. 2. 2.]\n",
      "tensor([2., 2., 2., 2., 2.], dtype=torch.float64)\n"
     ]
    }
   ],
   "source": [
    "# numpy -> torch\n",
    "import numpy as np\n",
    "a = np.ones(5)\n",
    "b = torch.from_numpy(a)\n",
    "np.add(a, 1, out=a)\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[1., 1.],\n",
      "        [1., 1.]], requires_grad=True)\n",
      "tensor([[3., 3.],\n",
      "        [3., 3.]], grad_fn=<AddBackward0>)\n",
      "<AddBackward0 object at 0x000001DB4A8B5518>\n"
     ]
    }
   ],
   "source": [
    "# Autograd: Automatic Differentiation\n",
    "x = torch.ones(2, 2, requires_grad=True)\n",
    "print(x)\n",
    "y = x + 2\n",
    "print(y)\n",
    "print(y.grad_fn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[27., 27.],\n",
      "        [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)\n"
     ]
    }
   ],
   "source": [
    "z = y * y * 3\n",
    "out = z.mean()\n",
    "print(z, out)\n",
    "# requires_grad_() 可以改变 tensor 的 requires_grad 属性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[4.5000, 4.5000],\n",
      "        [4.5000, 4.5000]])\n"
     ]
    }
   ],
   "source": [
    "# out.backward()\n",
    "print(x.grad)  # out = z.sum() / 4 --> d(out)/d(x) = 3*2*(x+2) / 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([-1079.4347,  1377.7787,  -126.5548], grad_fn=<MulBackward0>)\n"
     ]
    }
   ],
   "source": [
    "# Jacobian\n",
    "x = torch.randn(3, requires_grad=True)\n",
    "y = x * 2\n",
    "while y.data.norm() < 1000:\n",
    "    y = y * 2\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])\n"
     ]
    }
   ],
   "source": [
    "v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)\n",
    "y.backward(v)\n",
    "print(x.grad)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
